using System;
using System.Collections.Generic;
using System.Management.Automation;
using System.IO;
using System.Globalization;

namespace PSSymbolStore.Commands
{
    [Cmdlet(VerbsCommon.Get, "Transaction", 
        SupportsShouldProcess = false,
        DefaultParameterSetName = "IndividualTransactions")]
    public class GetTransactionsCommand : TransactionCommandBase
    {
        [Parameter(Position = 2,
            Mandatory = false,
            ParameterSetName = "AllTransactions",
            ValueFromPipeline = false,
            ValueFromPipelineByPropertyName = false,
            ValueFromRemainingArguments = false,
            HelpMessage = "Retrieve all transactions")]
        public SwitchParameter All { get; set; }

        [Parameter(Position = 3,
            Mandatory = false,
            HelpMessage = "Include more details that make up each transaction, such as the list of files making up the transaction")]
        public SwitchParameter IncludeDetails { get; set; }

        protected override bool CreateSymbolStore
        {
            get
            {
                return false;
            }
        }

        private TransactionFileParser _parser;

        protected override void BeginProcessing()
        {
            base.BeginProcessing();

            _parser = new TransactionFileParser(SymbolStoreObject.ServerFile, true);
        }

        protected override void ProcessRecord()
        {
            List<TransactionFileEntry> entries = null;

            if (All)
            {
                entries = _parser.Parse();
            }
            else
            {
                if ((TransactionId != null) && (TransactionId.Length > 0))
                {
                    var sortedTranList = new List<string>(TransactionId);
                    sortedTranList.Sort();

                    entries = _parser.Parse(delegate(PreParseEventArgs e)
                    {
                        // Default not to parse, and to continue
                        e.ShouldParse = false;
                        e.Cancel = false;

                        if (String.IsNullOrEmpty(e.Line) || (e.Line.Length < 10))
                        {
                            return;
                        }

                        // If the first part of e.Line
                        // starts with something found in transactions
                        // then we should process
                        // And if we've processed everything in transactions,
                        // then we should stop (cancel)
                        string tranId = e.Line.Substring(0, 10);
                        if (sortedTranList.Contains(tranId))
                        {
                            e.ShouldParse = true;
                            sortedTranList.Remove(tranId);

                            if (sortedTranList.Count == 0)
                            {
                                // We're done!
                                e.Cancel = true;
                            }
                        }
                    });
                }
            }

            // If we successfully parsed some entries
            if (entries != null)
            {
                foreach (TransactionFileEntry entry in entries)
                {
                    Transaction t = CreateTransaction(entry);
                    if (t != null)
                    {
                        WriteObject(t);
                    }
                }
            }
        }

        private Transaction CreateTransaction(TransactionFileEntry entry)
        {
            Transaction result = null;

            if (entry == null)
            {
                return null;
            }

            if (String.Equals(entry.TransactionType, "add", StringComparison.InvariantCultureIgnoreCase))
            {
                var addTrans = new AddTransaction(entry.TransactionId, TransactionType.Add);
                DateTime tranDateTime;
                string dateTimeField = String.Format("{0} {1}", entry.TransactionDate, entry.TransactionTime);
                if (DateTime.TryParseExact(dateTimeField, "MM/dd/yyyy HH:mm:ss", CultureInfo.InvariantCulture, DateTimeStyles.None, out tranDateTime))
                {
                    addTrans.TransactionDateTime = tranDateTime;
                }
                else
                {
                    WriteDebug("Unable to parse date time from file: " + dateTimeField);
                    addTrans.TransactionDateTime = DateTime.MinValue;
                }
                if (String.Equals(entry.FileOrPointer, "file", StringComparison.InvariantCultureIgnoreCase))
                {
                    addTrans.FileOrPointer = TransactionUploadType.File;
                }
                else if (String.Equals(entry.FileOrPointer, "ptr", StringComparison.InvariantCultureIgnoreCase))
                {
                    addTrans.FileOrPointer = TransactionUploadType.Pointer;
                }
                addTrans.Product = entry.Product;
                addTrans.Version = entry.Version;
                addTrans.Comment = entry.Comment;

                // Check if locked
                addTrans.Locked = File.Exists(SymbolStoreObject.GetTransactionLockedFile(entry.TransactionId));

                if (IncludeDetails)
                {
                    //addTrans.Fill();
                }
                result = addTrans;
            }
            else if (String.Equals(entry.TransactionType, "del", StringComparison.InvariantCultureIgnoreCase))
            {
                // Not supported, at the moment
            }
            else
            {
                WriteError(new ErrorRecord(null, "Unable to create transaction for transaction id: " + entry.TransactionId, ErrorCategory.InvalidData, entry));
            }

            return result;
        }
    }
}
